/************************************
*  Copyright (C) 2010 Julien MOTTIN.
*  Contact: julien.mottin@gueydan.eu
*
*  This file is part of Gueydan.
*
*  Gueydan is free software: you can redistribute it and/or modify
*  it under the terms of the GNU General Public License as published by
*  the Free Software Foundation, either version 3 of the License, or
*  (at your option) any later version.
*
*  Gueydan is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU General Public License for more details.
*
*  You should have received a copy of the GNU General Public License
*  along with Gueydan.  If not, see <http://www.gnu.org/licenses/>.
*
*************************************/
// Local
#include "yeast.h"
#include "xmldico.h"

// QtXml
#include <QDomNode>
#include <QDomElement>
#include <QDomDocument>
#include <QDomNodeList>

Yeast::Yeast(const QString &iName,
             const int iVersion,
             const YeastType iType,
             const YeastForm iForm,
             const Volume &iAmount)
:BeerXMLObject(iName,iVersion)
,_Type(iType)
,_Form(iForm)
,_AmountV(iAmount)
,_AmountW(0)
,_AmountIsWeight(false)
,_Laboratory()
,_ProductID()
,_MinTemperature(100)
,_MaxTemperature(0)
,_Flocculation(YFlUnset)
,_Attenuation(0)
,_Notes()
,_BestFor()
,_TimesCultured(0)
,_MaxReuse(0)
,_AddToSecondary(false)
{
}

Yeast::Yeast(const QString &iName,
             const int iVersion,
             const YeastType iType,
             const YeastForm iForm,
             const Weight &iAmount)
:BeerXMLObject(iName,iVersion)
,_Type(iType)
,_Form(iForm)
,_AmountV(0)
,_AmountW(iAmount)
,_AmountIsWeight(true)
,_Laboratory()
,_ProductID()
,_MinTemperature(100)
,_MaxTemperature(0)
,_Flocculation(YFlUnset)
,_Attenuation(0)
,_Notes()
,_BestFor()
,_TimesCultured(0)
,_MaxReuse(0)
,_AddToSecondary(false)
{
}

Yeast::Yeast()
:BeerXMLObject()
,_Type(YTAle)
,_Form(YFLiquid)
,_AmountV(0)
,_AmountW(0)
,_AmountIsWeight(false)
,_Laboratory()
,_ProductID()
,_MinTemperature(100)
,_MaxTemperature(0)
,_Flocculation(YFlUnset)
,_Attenuation(0)
,_Notes()
,_BestFor()
,_TimesCultured(0)
,_MaxReuse(0)
,_AddToSecondary(false)
{
}

Yeast::~Yeast()
{
}

bool Yeast::operator==(const Yeast &iOther) const
{
    return ((*this).BeerXMLObject::operator==(iOther) &&
            _Type == iOther._Type &&
            _Form == iOther._Form &&
            _AmountV == iOther._AmountV &&
            _AmountW == iOther._AmountW &&
            _AmountIsWeight == iOther._AmountIsWeight &&
            _Laboratory == iOther._Laboratory &&
            _ProductID == iOther._ProductID &&
            _MinTemperature == iOther._MinTemperature &&
            _MaxTemperature == iOther._MaxTemperature &&
            _Flocculation == iOther._Flocculation &&
            _Attenuation == iOther._Attenuation &&
            _Notes == iOther._Notes &&
            _BestFor == iOther._BestFor &&
            _TimesCultured == iOther._TimesCultured &&
            _MaxReuse == iOther._MaxReuse &&
            _AddToSecondary == iOther._AddToSecondary);
}

bool Yeast::operator!=(const Yeast &iOther) const
{
    return (!((*this)==iOther));
}

int Yeast::CreateFromXMLNode(const QDomNode &iNode)
{
    int oRC = 1;
    if (!iNode.isNull())
    {
        QDomElement YeastElement;

        // Case Document : check if doc has only one Yeast element
        if (iNode.isDocument())
        {
            QDomDocument YeastDoc = iNode.toDocument();
            QDomNodeList YeastList = YeastDoc.elementsByTagName(YEAST);
            if (YeastList.length()==1)
                YeastElement = YeastList.item(0).toElement();
        }
        // Default : cast to element
        else
            YeastElement = iNode.toElement();

        // Check element consistency
        if (!YeastElement.isNull() && YEAST==YeastElement.tagName())
        {
            // Check existence of mandatory elements
            bool YeastName = false;
            bool YeastVersion = false;
            bool YeastAmount = false;
            bool YeastType = false;
            bool YeastForm = false;
            _AmountIsWeight = false;
            QString amount;
            QDomNode node = YeastElement.firstChild();
            while (!node.isNull())
            {
                if (node.isElement())
                {
                    QDomElement elem = node.toElement();
                    QString name = elem.tagName();
                    QString text = elem.text();
                    if (name==YEAST_NAME)
                    {
                        _Name = text;
                        YeastName = true;
                    }
                    else if (name==YEAST_VERSION)
                    {
                        bool ok = false;
                        int v = text.toInt(&ok);
                        if (ok)
                        {
                            _Version = v;
                            YeastVersion = true;
                        }
                    }
                    else if (name==YEAST_TYPE)
                    {
                        QString type = text.toLower();
                        YeastType = true;
                        if (type==YEAST_TYPE_ALE.toLower())
                            _Type = YTAle;
                        else if (type==YEAST_TYPE_LAGER.toLower())
                            _Type = YTLager;
                        else if (type==YEAST_TYPE_WHEAT.toLower())
                            _Type = YTWheat;
                        else if (type==YEAST_TYPE_WINE.toLower())
                            _Type = YTWine;
                        else if (type==YEAST_TYPE_CHAMPAGNE.toLower())
                            _Type = YTChampagne;
                        else
                        {
                            YeastType = false;
                            break;
                        }
                    }
                    else if (name==YEAST_FORM)
                    {
                        QString type = text.toLower();
                        YeastForm = true;
                        if (type==YEAST_FORM_LIQUID.toLower())
                            _Form = YFLiquid;
                        else if (type==YEAST_FORM_DRY.toLower())
                            _Form = YFDry;
                        else if (type==YEAST_FORM_SLANT.toLower())
                            _Form = YFSlant;
                        else if (type==YEAST_FORM_CULTURE.toLower())
                            _Form = YFCulture;
                        else
                        {
                            YeastForm = false;
                            break;
                        }

                    }
                    else if (name==YEAST_AMOUNT)
                    {
                        amount = text;
                        YeastAmount = true;
                    }
                    else if (name==YEAST_AMOUNTISWEIGHT)
                    {
                        _AmountIsWeight = false;
                        if (text.toLower()=="true")
                            _AmountIsWeight = true;
                    }
                    else if (name==YEAST_LABORATORY)
                    {
                        _Laboratory = text;
                    }
                    else if (name==YEAST_PRODUCTID)
                    {
                        _ProductID = text;
                    }
                    else if (name==YEAST_MINTEMP)
                    {
                        Temperature Temp;
                        bool ok = false;
                        Temp.FromString(text,&ok);
                        if (ok)
                            _MinTemperature = Temp;
                    }
                    else if (name==YEAST_MAXTEMP)
                    {
                        Temperature Temp;
                        bool ok = false;
                        Temp.FromString(text,&ok);
                        if (ok)
                            _MaxTemperature = Temp;
                    }
                    else if (name==YEAST_FLOCCULATION)
                    {
                        QString floc=text.toLower();
                        if (floc==YEAST_FLOC_LOW.toLower())
                            _Flocculation = YFlLow;
                        else if (floc==YEAST_FLOC_MEDIUM.toLower())
                            _Flocculation = YFlMedium;
                        else if (floc==YEAST_FLOC_HIGH.toLower())
                            _Flocculation = YFlHigh;
                        else if (floc==YEAST_FLOC_VERYHIGH.toLower())
                            _Flocculation = YFlVeryHigh;
                    }
                    else if (name==YEAST_NOTES)
                    {
                        _Notes = text;
                    }
                    else if (name==YEAST_ATTENUATION)
                    {
                        bool ok = false;
                        float v = text.toFloat(&ok);
                        if (ok)
                            _Attenuation = v;
                    }
                    else if (name==YEAST_BESTFOR)
                    {
                        _BestFor = text;
                    }
                    else if (name==YEAST_TIMESCULTURED)
                    {
                        bool ok = false;
                        int v = text.toInt(&ok);
                        if (ok)
                            _TimesCultured = v;
                    }
                    else if (name==YEAST_MAXREUSE)
                    {
                        bool ok = false;
                        int v = text.toInt(&ok);
                        if (ok)
                            _MaxReuse = v;
                    }
                    else if (name==YEAST_ADDTOSECONDARY)
                    {
                        if (text.toLower()=="true")
                            _AddToSecondary = true;
                    }
                }

                // Iterate
                node = node.nextSibling();
            }

            // Check & update output
            if (YeastName && YeastVersion && YeastAmount && YeastType && YeastForm)
            {
                bool ok = false;
                if (_AmountIsWeight)
                {
                    Weight w;
                    w.FromString(amount,&ok);
                    if (ok)
                        _AmountW = w;
                }
                else
                {
                    Volume v;
                    v.FromString(amount,&ok);
                    if (ok)
                        _AmountV = v;
                }

                // Success
                if (ok)
                {
                    oRC = 0;
                }
            }
        }
    }

    return oRC;
}

int Yeast::ToXMLNode(QDomNode &iParentNode) const
{

    int oRC = 1;

    // First, create valid element node
    QDomDocument doc = iParentNode.ownerDocument();
    QDomElement YeastNode = doc.createElement(YEAST);
    if (!YeastNode.isNull())
    {
        if (!_Name.isEmpty() && _Version>0)
        {
            QDomElement Node;
            QDomText Text;
            QString str;

            // Name
            Node = doc.createElement(YEAST_NAME);
            Q_ASSERT(!Node.isNull());
            Text = doc.createTextNode(_Name);
            Q_ASSERT(!Text.isNull());
            Node.appendChild(Text);
            YeastNode.appendChild(Node);

            // Version
            Node = doc.createElement(YEAST_VERSION);
            Q_ASSERT(!Node.isNull());
            Text = doc.createTextNode(QString::number(_Version));
            Q_ASSERT(!Text.isNull());
            Node.appendChild(Text);
            YeastNode.appendChild(Node);

            // Type
            switch (_Type)
            {
            case YTAle:
                str = YEAST_TYPE_ALE;
                break;
            case YTLager:
                str = YEAST_TYPE_LAGER;
                break;
            case YTWheat:
                str = YEAST_TYPE_WHEAT;
                break;
            case YTWine:
                str = YEAST_TYPE_WINE;
                break;
            case YTChampagne:
                str = YEAST_TYPE_CHAMPAGNE;
                break;
            }
            Node = doc.createElement(YEAST_TYPE);
            Q_ASSERT(!Node.isNull());
            Text = doc.createTextNode(str);
            Q_ASSERT(!Text.isNull());
            Node.appendChild(Text);
            YeastNode.appendChild(Node);

            // Form
            switch (_Form)
            {
            case YFLiquid:
                str = YEAST_FORM_LIQUID;
                break;
            case YFDry:
                str = YEAST_FORM_DRY;
                break;
            case YFSlant:
                str = YEAST_FORM_SLANT;
                break;
            case YFCulture:
                str = YEAST_FORM_CULTURE;
                break;
            }
            Node = doc.createElement(YEAST_FORM);
            Q_ASSERT(!Node.isNull());
            Text = doc.createTextNode(str);
            Q_ASSERT(!Text.isNull());
            Node.appendChild(Text);
            YeastNode.appendChild(Node);

            // Amount
            if (_AmountIsWeight)
            {
                // Weight
                str = QString::number(_AmountW.Value(Kilogram));

                // Write flag
                Node = doc.createElement(YEAST_AMOUNTISWEIGHT);
                Q_ASSERT(!Node.isNull());
                Text = doc.createTextNode("TRUE");
                Q_ASSERT(!Text.isNull());
                Node.appendChild(Text);
                YeastNode.appendChild(Node);
            }
            else
            {
                // Volume
                str = QString::number(_AmountV.Value(Liter));
            }
            Node = doc.createElement(YEAST_AMOUNT);
            Q_ASSERT(!Node.isNull());
            Text = doc.createTextNode(str);
            Q_ASSERT(!Text.isNull());
            Node.appendChild(Text);
            YeastNode.appendChild(Node);

            // Laboratory
            if (!_Laboratory.isEmpty())
            {
                Node = doc.createElement(YEAST_LABORATORY);
                Q_ASSERT(!Node.isNull());
                Text = doc.createTextNode(_Laboratory);
                Q_ASSERT(!Text.isNull());
                Node.appendChild(Text);
                YeastNode.appendChild(Node);
            }

            // ProductID
            if (!_ProductID.isEmpty())
            {
                Node = doc.createElement(YEAST_PRODUCTID);
                Q_ASSERT(!Node.isNull());
                Text = doc.createTextNode(_ProductID);
                Q_ASSERT(!Text.isNull());
                Node.appendChild(Text);
                YeastNode.appendChild(Node);
            }

            // MinTemperature
            if (_MinTemperature<_MaxTemperature)
            {
                Node = doc.createElement(YEAST_MINTEMP);
                Q_ASSERT(!Node.isNull());
                Text = doc.createTextNode(QString::number(_MinTemperature.Value(Celsius)));
                Q_ASSERT(!Text.isNull());
                Node.appendChild(Text);
                YeastNode.appendChild(Node);

                // MaxTemperature
                Node = doc.createElement(YEAST_MAXTEMP);
                Q_ASSERT(!Node.isNull());
                Text = doc.createTextNode(QString::number(_MaxTemperature.Value(Celsius)));
                Q_ASSERT(!Text.isNull());
                Node.appendChild(Text);
                YeastNode.appendChild(Node);
            }

            // Flocculation
            if (YFlUnset!=_Flocculation)
            {
                switch (_Flocculation)
                {
                case YFlLow:
                    str = YEAST_FLOC_LOW;
                    break;
                case YFlMedium:
                    str = YEAST_FLOC_MEDIUM;
                    break;
                case YFlHigh:
                    str = YEAST_FLOC_HIGH;
                    break;
                case YFlVeryHigh:
                    str = YEAST_FLOC_VERYHIGH;
                    break;
                default:
                    str = "";
                    break;
                }
                Node = doc.createElement(YEAST_FLOCCULATION);
                Q_ASSERT(!Node.isNull());
                Text = doc.createTextNode(str);
                Q_ASSERT(!Text.isNull());
                Node.appendChild(Text);
                YeastNode.appendChild(Node);
            }

            // Attenuation
            if (_Attenuation>0)
            {
                Node = doc.createElement(YEAST_ATTENUATION);
                Q_ASSERT(!Node.isNull());
                Text = doc.createTextNode(QString::number(_Attenuation));
                Q_ASSERT(!Text.isNull());
                Node.appendChild(Text);
                YeastNode.appendChild(Node);
            }

            // Notes
            if (!_Notes.isEmpty())
            {
                Node = doc.createElement(YEAST_NOTES);
                Q_ASSERT(!Node.isNull());
                Text = doc.createTextNode(_Notes);
                Q_ASSERT(!Text.isNull());
                Node.appendChild(Text);
                YeastNode.appendChild(Node);
            }

            // Best for
            if (!_Notes.isEmpty())
            {
                Node = doc.createElement(YEAST_BESTFOR);
                Q_ASSERT(!Node.isNull());
                Text = doc.createTextNode(_BestFor);
                Q_ASSERT(!Text.isNull());
                Node.appendChild(Text);
                YeastNode.appendChild(Node);
            }

            // Times cultured
            if (_TimesCultured>0)
            {
                Node = doc.createElement(YEAST_TIMESCULTURED);
                Q_ASSERT(!Node.isNull());
                Text = doc.createTextNode(QString::number(_TimesCultured));
                Q_ASSERT(!Text.isNull());
                Node.appendChild(Text);
                YeastNode.appendChild(Node);
            }

            // Max reuse
            if (_MaxReuse>0)
            {
                Node = doc.createElement(YEAST_MAXREUSE);
                Q_ASSERT(!Node.isNull());
                Text = doc.createTextNode(QString::number(_MaxReuse));
                Q_ASSERT(!Text.isNull());
                Node.appendChild(Text);
                YeastNode.appendChild(Node);
            }

            // Add to secondary
            if (_AddToSecondary)
            {
                Node = doc.createElement(YEAST_ADDTOSECONDARY);
                Q_ASSERT(!Node.isNull());
                Text = doc.createTextNode("TRUE");
                Q_ASSERT(!Text.isNull());
                Node.appendChild(Text);
                YeastNode.appendChild(Node);
            }

            // Update output
            QDomNode zeNode = iParentNode.appendChild(YeastNode);
            if (!zeNode.isNull())
                oRC = 0;
        }
    }

    return oRC;
}
